import axios, {
	AxiosInstance,
	AxiosError,
	AxiosRequestConfig,
	AxiosResponse,
} from "axios"
import NProgress from "@/config/nprogress"
// antd message组件
import type { ResultData } from "./typing/common"
import pendings, { stringfyConfig } from "./axiosCancel"
import { isFunction } from "@/utils/is"
import { getItem } from "@/utils/storage"
console.log(process.env.REACT_APP_BASE_API)

const config = {
	// 默认地址请求地址，可在 .env 开头文件中修改
	baseURL: process.env.REACT_APP_BASE_API,
	// 设置超时时间（10s）
	timeout: 10000,
	// 跨域时候允许携带凭证
	withCredentials: true,
}
class RequestHttp {
	private service: AxiosInstance
	config: AxiosRequestConfig | null
	constructor(config: AxiosRequestConfig) {
		this.config = null
		this.service = axios.create(config)
		// 请求拦截器
		this.service.interceptors.request.use(
			(config) => {
				if (config.url !== "/admin/acl/index/login") {
					const token = getItem("token")
					if (token) {
						config.headers.token = token
					}
				}
				NProgress.start()
				this.config = config
				const cancel = pendings.pendingMap.get(stringfyConfig(config))
				if (cancel && isFunction(cancel)) {
					// 有取消函数，说明请求未结束，请求重复了
					cancel()
				} else {
					// 没有，说明时首次请求，或者是请求已经完成后的第二次请求
					pendings.add(config)
				}
				return config
			},
			(error: AxiosError) => {
				return Promise.reject(error)
			},
		)
		// 响应拦截器
		this.service.interceptors.response.use(
			(response: AxiosResponse) => {
				NProgress.done()
				pendings.remove(this.config as AxiosRequestConfig)
				this.config = null
				return response.data
			},
			(error: AxiosError) => {
				return Promise.reject(error)
			},
		)
	}

	request<T>(config: AxiosRequestConfig) {
		return this.service.request<any, T>(config)
	}

	get<T, K>(url: string, params?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, params, ..._object, method: "GET" })
	}
	post<T, K>(url: string, data?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, data, ..._object, method: "POST" })
	}
	put<T, K>(url: string, data?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, data, ..._object, method: "PUT" })
	}
	delete<T, K>(url: string, data?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, data, ..._object, method: "DELETE" })
	}
}

const http = new RequestHttp(config)
export default http
